#include <iostream>
#include <pthread.h>
#include <queue>
namespace BlockQueue
{
    static int SIZE_MAX = 5; // 队列最大容量
    template <class T>
    class blockqueue
    {
        bool Full() { return _q.size() >= SIZE_MAX; }
        bool Empty() { return _q.empty(); }

    public:
        blockqueue(int sz = SIZE_MAX) : _sz(sz), _psleep(0), _csleep(0)
        {
            pthread_mutex_init(&_produce_mutex, nullptr);
            pthread_mutex_init(&_consume_mutex, nullptr);
            pthread_cond_init(&_produce_cond, nullptr);
            pthread_cond_init(&_consume_cond, nullptr);
        }
        ~blockqueue()
        {
            pthread_mutex_destroy(&_produce_mutex);
            pthread_mutex_destroy(&_consume_mutex);
            pthread_cond_destroy(&_produce_cond);
            pthread_cond_destroy(&_consume_cond);
        }
        void Produce(const T &data)
        {
            // 申请锁
            pthread_mutex_lock(&_mutex);
            while (Full())
            {
                // wait
                _psleep++;
                pthread_cond_wait(&_produce_cond, &mutex);
                _psleep--;
            }
            // 生产数据
            _q / push(data);
            if (_csleep > 0)
            {
                // 唤醒消费者线程
                pthread_cond_signal(&_consume_cond);
            }
            pthread_mutex_unlock(&_mutex);
        }
        void Consume(T *data)
        {
            // 申请锁
            pthread_mutex_lock(&_mutex);
            while (Empty())
            {
                // wait
                _csleep++;
                pthread_cond_wait(&_consume_cond, &_mutex);
                _csleep--;
            }
            *data = _q.pop();
            if (_psleep > 0)
            {
                //唤醒生产者线程
                pthread_cond_signal(&_produce_cond);
            }
            pthread_mutex_unlock(&_mutex);
        }

    private:
        std::queue<T> _q;             // 队列
        pthread_mutex_t _mutex;       // 互斥量
        pthread_cond_t _produce_cond; // 生产者条件变量
        pthread_cond_t _consume_cond; // 消费者条件变量
        int _psleep;                  // 生产者阻塞等待的线程数
        int _csleep;                  // 消费者阻塞等待的线程数
    };
}

// #include <iostream>
// #include <pthread.h>
// #include <queue>
// namespace BlockQueue
// {
//     static int size_val = 5;
//     template <class T>
//     class blockqueue
//     {
//         bool Full() { return _q.size() >= size_val; }
//         bool Empty() { return _q.empty(); }

//     public:
//         blockqueue(int sz = size_val) : _c_w_cnt(0), _c_r_cnt(0)
//         {
//             pthread_mutex_init(&_mutex, nullptr);
//             pthread_cond_init(&_w_cond, nullptr);
//             pthread_cond_init(&_r_cond, nullptr);
//         }

//         void Write(const T &data) //
//         {
//             pthread_mutex_lock(&_mutex); // 申请锁
//             // if (Full())
//             while (Full())
//             {
//                 // 没有剩余空间
//                 _c_w_cnt++;
//                 pthread_cond_wait(&_w_cond, &_mutex); // 阻塞等待
//                 _c_w_cnt--;
//             }
//             // 插入数据
//             _q.push(data);
//             // 唤醒读者
//             if (_c_r_cnt > 0)
//             {
//                 std::cout << "唤醒读者" << std::endl;
//                 pthread_cond_signal(&_r_cond);
//             }
//             // 释放锁
//             pthread_mutex_unlock(&_mutex);
//             usleep(100);
//         }
//         void Read(T *data)
//         {
//             pthread_mutex_lock(&_mutex);
//             while (Empty())
//             {
//                 // 没有内容
//                 _c_r_cnt++;
//                 pthread_cond_wait(&_r_cond, &_mutex);
//                 _c_r_cnt--;
//             }
//             // 读取数据
//             *data = _q.front();
//             _q.pop();
//             // 唤醒写者
//             if (_c_w_cnt > 0)
//             {
//                 std::cout << "唤醒写者" << std::endl;
//                 pthread_cond_signal(&_w_cond);
//             }
//             // 释放锁
//             pthread_mutex_unlock(&_mutex);
//             usleep(100);
//         }

//     private:
//         std::queue<T> _q;
//         pthread_mutex_t _mutex;
//         pthread_cond_t _w_cond;
//         pthread_cond_t _r_cond;
//         int _c_w_cnt; // 写，阻塞线程数量
//         int _c_r_cnt; // 读，阻塞线程数量
//         int _size;
//     };
// }